import { EventsRes } from '@amcax/base';
import { ctx2 } from '@app-cad/module';
import { addDimension } from '@app-cad/common/utils';
import {
  SKETCH_CENTEREVENTS,
  sketchEventCenter,
} from '@app-cad/environments/nextcad/events/SketchEventCenter';
import { Vector2tuple, Vector3 } from 'three-legacy';
import CmdBase from '../../CmdBase';
import { dimRender } from '../cmd-render-pick/render';
import { DimLinear } from '../dimension/DimLinear';
import { AnnotationType } from '../dimension/types';
import { MouseState, State } from './types';

export default class CmdInteractor extends CmdBase {
  constraintType: 4;
  drawState: MouseState = State.NONE;
  lineVerticalLength: number = 0;
  curveIds: string[] = [];
  dimVertical: DimLinear;
  point1: Vector3 = null;
  point2: Vector3 = null;
  endPoint: Vector3 = null;
  labelPosLV: Vector3 = new Vector3();
  isExist: boolean = false;
  vertices: Vector2tuple[][];
  types: string;

  constructor() {
    super();
    this.registerEvents();
    this.picker.clickNull();
  }

  reset() {
    this.drawState = State.NONE;
    this.pickSnapInfo = null;
    this.types = null;
    this.curveIds = [];
  }

  unregisterEvents() {
    sketchEventCenter()
      .off(SKETCH_CENTEREVENTS.POINTERDOWN, this.onMouseDown)
      .off(SKETCH_CENTEREVENTS.POINTERUP, this.onMouseUp)
      .off(SKETCH_CENTEREVENTS.POINTERMOVE, this.onMouseMove)
      .off(SKETCH_CENTEREVENTS.KEYUP, this.onKeyUp)
      .setDefault();
  }

  registerEvents() {
    sketchEventCenter()
      .setState('dimVertical')
      .on(SKETCH_CENTEREVENTS.POINTERDOWN, this.onMouseDown)
      .on(SKETCH_CENTEREVENTS.POINTERUP, this.onMouseUp)
      .on(SKETCH_CENTEREVENTS.POINTERMOVE, this.onMouseMove)
      .on(SKETCH_CENTEREVENTS.KEYUP, this.onKeyUp)
      .addExit(this.destroy.bind(this));
  }

  onMouseDown = ({ button }: EventsRes) => {
    if (button.onLeft && this.pickSnapInfo) {
      this.dimVertical?.unClickFocus();
    }
  };
  onMouseUp = ({ button }: EventsRes) => {
    if (button.onLeft) {
      if (this.drawState < State.DRAWTWO) {
        if (
          this.pickSnapInfo?.type === 'Line' ||
          this.pickSnapInfo?.type === 'Point'
        ) {
          if (
            this.types === 'Line' ||
            this.curveIds.includes(this.pickSnapInfo.id)
          ) {
            this.dimVertical.labelFoucs();
            return;
          } else {
            this.curveIds.push(this.pickSnapInfo.id);
            if (this.drawState === State.NONE) {
              this.vertices = [this.pickSnapInfo.vertices];
            } else {
              this.vertices.push(this.pickSnapInfo.vertices);
            }
            this.addLine();
            this.drawState = this.drawState + 1;
            this.types = this.pickSnapInfo.type;
            this.dimVertical.labelFoucs();
          }
        }
      }
    } else if (button.onRight && !this.closeRightClick) {
      this.drawState = State.NONE;
      this.reset();
      this.releaseObjects();
    }
  };

  onMouseMove = (e: EventsRes) => {
    this.setMouseWV(e, false, false);
    if (this.drawState === State.DRAWONE || this.drawState === State.DRAWTWO) {
      this.dimVertical.update({
        labelPos: this.mouseWV,
      });
      ctx2.viewer.requestRender();
    }
  };
  callback = (status: 'focus' | 'blur') => {
    if (status === 'focus' && this.drawState <= State.DRAWTWO) {
      this.drawState = State.INPUT;
    } else if (this.drawState === State.INPUT && status === 'blur') {
      this.finishDraw();
      this.reset();
    }
  };
  addLine = () => {
    if (!this.dimVertical) {
      this.dimVertical = new DimLinear({
        curveIds: this.curveIds,
        dimConstraint: AnnotationType.DistanceYAnno,
        lineVertices: this.vertices,
        labelPos: this.mouseWV,
        callback: this.callback,
      });
      this.dimVertical.addTo(this.assisGroup);
    } else {
      this.dimVertical.update({
        curveIds: this.curveIds,
        lineVertices: this.vertices,
        labelPos: this.mouseWV,
        callback: this.callback,
      });
    }
    this.isExist = dimRender().isExistDim({
      objects: this.curveIds,
      type: 4,
    });
    if (this.isExist) {
      this.dimVertical.setDisable();
    }
    this.dimVertical?.labelFoucs();
  };
  finishDraw = async () => {
    if (this.dimVertical?.getVal() === 0 && this.curveIds.length === 1) {
      this.releaseObjects();
      return;
    }
    addDimension(
      this.sketchId,
      {
        objects: this.curveIds,
        type: AnnotationType.DistanceYAnno,
        value: this.dimVertical.getVal(),
        points: this.dimVertical.getPosLv(),
      },
      this.isExist,
    ).finally(() => {
      this.releaseObjects();
    });
  };

  releaseObjects() {
    this.assisGroup.clear();
    this.dimVertical?.destroy();
    this.dimVertical = null;
    ctx2.viewer.requestRender();
  }
}
